
#include <stdatomic.h>
#include <sys/types.h>
#include <unistd.h>
#include "queue.c"

typedef struct __lock_t {
	// flag表示锁有没有被线程需求，锁可以同时被多个线程所等候，
	// 仅当没有线程等候时才会设置为 0 
	int flag;
	// guard 是 lock 和 unlock 过程的一个自旋锁
	int guard;
	queue_t *wait_queue;
} lock_t;

void init(lock_t *mutex) {
	mutex->flag = 0;
	mutex->guard = 0;
	queue_init(mutex->wait_queue);
}

void lock(lock_t *mutex) 
{
	int key = 0;
	while (!atomic_compare_exchange_strong(&mutex->guard, &key, 1))
    {
    	key = 0;
	} //acquire guard lock by spinning 

	if (mutex->flag == 0) 
	{
		mutex->flag = 1; //acquire guard lock by spinning
		mutex->guard = 0;
	} 
	else
	{
		// 将当前线程放入到队列中
		queue_add(mutex->queue, gettid());
		mutex->guard = 0;
		// 伪代码，阻塞当前线程，需要发起一次系统调用
		park();
	}
}
void unlock(lock_t *mutex) 
{	
	int key = 0;
    while (!atomic_compare_exchange_strong(&mutex->guard, &key, 1))
    {
	    key = 0;
    } //acquire guard lock by spinning
	
	if (queue_empty(mutex->wait_queue))
	{
		mutex->flag = 0; 
	}
	else
	{
		// 伪代码，唤醒队列中的一个线程，需要发起系统调用
		unpark(queue_remove(mutex->wait_queue)); // hold lock
		// (for next thread!)
		mutex->guard = 0;
	}
}

